from datetime import datetime, timedelta

import pandas as pd


def get_mean_speed_duration(mean_speed_data, speed_limit, time_limit):
    # 处理列表a，均速小于40km/hq，且持续超过30分钟
    df_a = pd.DataFrame(mean_speed_data)
    a_intervals = []
    current_intervals = []
    for i in range(len(df_a) - 1):
        mean_speed_kmh = df_a['mean_speed'].iloc[i] * 3.6
        if mean_speed_kmh < speed_limit:
            current_intervals.append(df_a['transtime_up'].iloc[i])
        else:
            if current_intervals:
                duration = (current_intervals[-1] - current_intervals[0]).total_seconds()
                if duration >= time_limit:
                    a_intervals.append((current_intervals[0], current_intervals[-1]))
                current_intervals = []
    if current_intervals:
        if a_intervals == []:
            a_intervals.append((current_intervals[0], current_intervals[-1]))
            current_intervals = []

    return a_intervals


def get_slow_vehicl_duration(slow_vehicl_data, slow_limit, time_limit):
    # 处理字典b
    df_b = pd.Series(slow_vehicl_data).reset_index(name='value').rename(columns={'index': 'Group_Time'})
    b_intervals = []
    b_current_intervals = []
    for i in range(len(df_b) - 1):
        if df_b['value'].iloc[i] >= slow_limit:
            b_current_intervals.append(df_b['Group_Time'].iloc[i])
        else:
            if b_current_intervals:
                duration = (b_current_intervals[-1] - b_current_intervals[0]).total_seconds()
                if duration >= time_limit:
                    b_intervals.append((b_current_intervals[0], b_current_intervals[-1]))
                b_current_intervals = []
    if b_current_intervals:
        if b_intervals == []:
            b_intervals.append((b_current_intervals[0], b_current_intervals[-1]))
            b_current_intervals = []

    return b_intervals


def get_all_pass_rate_duration(all_pass_rate_data, pass_limit, time_limit):
    # 处理列表c
    df_c = pd.DataFrame(all_pass_rate_data)
    c_intervals = []
    c_current_intervals = []
    for i in range(len(df_c) - 1):
        if df_c['Percentage'].iloc[i] <= pass_limit:
            c_current_intervals.append(df_c['Group_Time'].iloc[i])
        else:
            if c_current_intervals:
                duration = (c_current_intervals[-1] - c_current_intervals[0]).total_seconds()
                if duration >= time_limit:
                    c_intervals.append((c_current_intervals[0], c_current_intervals[-1]))
                c_current_intervals = []

    return c_intervals


def get_time_duration(time_df, pass_limit, time_limit, time_interval):
    grouped = time_df.groupby(pd.Grouper(key='transtime_down', freq=time_interval)).size().reset_index(name='count')
    time_intervals = []
    time_current_intervals = []
    i_list = []
    for i in range(len(grouped) - 1):
        if grouped['count'].iloc[i] <= pass_limit:
            i_list.append(i)
            time_current_intervals.append(grouped['transtime_down'].iloc[i])
        else:
            if time_current_intervals:
                duration = (time_current_intervals[-1] - time_current_intervals[0]).total_seconds()
                if duration >= time_limit:
                    time_intervals.append((time_current_intervals[0], time_current_intervals[-1]))
                else:
                    last_num_list = []
                    if i >= 5:
                        for i_num in range(i-5, i):
                            last_num_list.append(grouped['count'].iloc[i_num])
                    if any(d > 20 for d in last_num_list):
                        if len(time_current_intervals) == 1:
                            time_current_intervals.append(time_current_intervals[0] + timedelta(minutes=5))
                        time_intervals.append((time_current_intervals[0], time_current_intervals[-1]))
                time_current_intervals = []
                i_list = []
    last_time = grouped['transtime_down'].iloc[-1]
    if last_time < last_time.replace(hour=23, minute=30):
        if time_current_intervals:
            duration = (last_time - time_current_intervals[0]).total_seconds()
            if duration <= time_limit:
                time_intervals.append((time_current_intervals[0], last_time.replace(hour=23, minute=30)))
            else:
                time_intervals.append((last_time, last_time.replace(hour=23, minute=30)))
        else:
            time_intervals.append((last_time, last_time.replace(hour=23, minute=30)))

    return time_intervals


def get_greater_time_duration(data_list, pass_limit, time_limit):
    greater_time_intervals = []
    greater_time_current_intervals = []
    for v in data_list:
        if v['percentage'] > pass_limit:
            greater_time_current_intervals.append(datetime.strptime(v['time_interval'], '%Y-%m-%d %H:%M:%S'))
        else:
            if greater_time_current_intervals:
                duration = (greater_time_current_intervals[-1] - greater_time_current_intervals[0]).total_seconds()
                if duration >= time_limit:
                    greater_time_intervals.append((greater_time_current_intervals[0], greater_time_current_intervals[-1]))
                greater_time_current_intervals = []
    return greater_time_intervals


def calculate_intersections(data_list):
    all_intervals = []
    for array in data_list:
        all_intervals.extend(array)

    all_intervals.sort(key=lambda x: x[0])

    intersections = []
    current_start = all_intervals[0][0]
    current_end = all_intervals[0][1]
    for interval in all_intervals[1:]:
        start, end = interval
        current_start = max(current_start, start)
        current_end = min(current_end, end)
        if current_start < current_end:
            intersections.append((current_start, current_end))
        else:
            current_start = start
            current_end = end
    return intersections


def merge_ranges(ranges):
    sorted_ranges = sorted(ranges, key=lambda x: x[0])
    merged = [sorted_ranges[0]]
    for current_start, current_end in sorted_ranges[1:]:
        last_start, last_end = merged[-1]
        if current_start <= last_end:
            merged[-1] = (last_start, max(last_end, current_end))
        else:
            merged.append((current_start, current_end))
    new_merged = []
    for (start, end) in merged:
        if (end - start) < timedelta(hours=20):
            new_merged.append((start, end))
    return new_merged


